﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;
using System.Collections.ObjectModel;

namespace Jiuyong
{
	namespace ViewModels
	{
		public abstract class FilesViewModel<TConfig,TItem>: ViewModelBase
			where TConfig:FilesConfig,new()
		{
			public FilesViewModel()
			{
				LoadSettings();
				InputStringSubcommands.Add("SelectSetting", r =>
				{
					if (String.IsNullOrWhiteSpace(r))
					{
						ConfigSettings.Remove(ConfigTitle);
					}
					else
					{
						TConfig cfg;//= ConfigSettings.GetOrNew(r,ConfigSettings.Default);
						lock (ConfigSettings)
						{
							if (ConfigSettings.Contains(r))
							{
								cfg = ConfigSettings[r];
							}
							else
							{
								cfg = new TConfig()
								{
									ConfigTitle = r
								};
								ConfigTitle = r;
								SaveConfig(cfg);
							}
						}
						ConfigSettings.Default = cfg;
					}
					OnConfigChanged();
				}, getDefaultText: () => ConfigTitle, dialogMessage: "选择或者输入新的配置名称，\r\n输入空的名称将删除当前配置：", getOtherTexts: () => ConfigSettings.Keys
);
			}

			protected void LoadSettings()
			{
				//ConfigSettings = new ConfigDictionary<TConfig>();
				//var ts = Config<TConfig[]>.Load();
				//if (null==ts)
				//{
				//}
				//else
				//{
				//    foreach (var item in ts)
				//    {
				//        ConfigSettings.Add(item);
				//    }
				//}
				//ConfigSetting = Config<TConfig>.Load();
				DateTime? st = null;
				ConfigSettings = Config<ConfigDictionary<TConfig>>.Load(ref st) ?? new ConfigDictionary<TConfig>();
				SaveTime = st;
				var cs	=	ConfigSettings.Default;
				//ConfigSetting = ConfigSettings.Configs.Default;
				LoadConfig(cs);
				
			}

			/// <summary>
			/// 将配置应用到程序中。
			/// </summary>
			/// <param name="cs"></param>
			protected virtual void LoadConfig(TConfig cs)
			{
				InputText = cs.InputText;
				InputPath = cs.InputPath;
				OutputText = cs.OutputText;
				OutputPath = cs.OutputPath;
				ConfigTitle = cs.ConfigTitle;
			}

			protected void SaveSettings()
			{
				var ct = ConfigTitle ?? "";
				TConfig cs;
				//cs = ConfigSettings.AddOrNew(ct,x => new TConfig()
				//{
				//    ConfigTitle = ""
				//});
				if (ConfigSettings.Contains(ct))
				{
					cs = ConfigSettings[ct];
				}
				else
				{
					cs = new TConfig()
					{
						ConfigTitle = ct
					};
					ConfigSettings.Add(cs);
				}

				SaveConfig(cs);

				ConfigSettings.Default = cs;

				//Config<ConfigDictionary<TConfig>>.Save(ConfigSettings);

				//var s = new ConfigDictionary<RehabFileConfig>();
				//Config<ConfigDictionary<RehabFileConfig>>.Save(s);

				//var s = new MultiConfig<TConfig>();
				//s.Configs.UnionWith(ConfigSettings);
				//s.Default = "";
				Config<ConfigDictionary<TConfig>>.Save(ConfigSettings);
			}

			/// <summary>
			/// 将程序当前配置存入配置对象中（以便保存）。
			/// </summary>
			/// <param name="cs"></param>
			public virtual void SaveConfig(TConfig cs)
			{
				cs.InputText = InputText;
				cs.InputPath = InputPath;
				cs.OutputText = OutputText;
				cs.OutputPath = OutputPath;
				cs.ConfigTitle = ConfigTitle;
			}

			//protected TConfig ConfigSetting ;
			//protected string selectedConfig = String.Empty;
			protected ConfigDictionary<TConfig> ConfigSettings = new ConfigDictionary<TConfig>();


			private string _inputPath;
			public string InputPath
			{
				get
				{
					return _inputPath;
				}

				set
				{
					_inputPath = value;
					OnPropertyChanged("InputPath");
				}
			}

			private string _inputText;
			public string InputText
			{
				get
				{
					return _inputText;
				}

				set
				{
					_inputText = value;
					OnPropertyChanged("InputText");
				}
			}

			private string _outputPath;
			public string OutputPath
			{
				get
				{
					return _outputPath;
				}

				set
				{
					_outputPath = value;
					OnPropertyChanged("OutputPath");
				}
			}

			private string _outputText;
			public string OutputText
			{
				get
				{
					return _outputText;
				}

				set
				{
					_outputText = value;
					OnPropertyChanged("OutputText");
				}
			}

			private DateTime? _saveTime = null;
			public DateTime? SaveTime
			{
				get
				{
					return _saveTime;
				}

				set
				{
					_saveTime = value;
					OnPropertyChanged("SaveTime");
				}
			}

			private ObservableCollection<TItem> _outputLines = new ObservableCollection<TItem>();
			public ObservableCollection<TItem> Items
			{
				get
				{
					return _outputLines;
				}

				set
				{
					_outputLines = value;
					OnPropertyChanged("Items");
				}
			}

			private object _fileContent;
			public object ItemContent
			{
				get
				{
					return _fileContent;
				}

				set
				{
					_fileContent = value;
					OnPropertyChanged("ItemContent");
				}
			}

			private object _selectedItem;
			public object SelectedItem
			{
				get
				{
					return _selectedItem;
				}

				set
				{
					_selectedItem = value;
					OnPropertyChanged("SelectedItem");
					OnSelectedItemChanged(this,_selectedItem,value);

				}
			}

			public virtual void OnSelectedItemChanged(object owner, object oldValue, object newValue)
			{
				var value = newValue as string;
				if (File.Exists(value))
				{
					ItemContent = File.ReadAllText(value);
				}
				else
				{
					ItemContent = null;
				}
			}

			private string _configTitle;
			public string ConfigTitle
			{
				get
				{
					return _configTitle;
				}

				set
				{
					_configTitle = value;
					OnPropertyChanged("ConfigTitle");
				}
			}

			public void GetInputString(object sender, ExecutedRoutedEventArgs e)
			{
				var panel = e.Parameter as Panel;
				Core.ShowTextDialog(r =>
				{
					InputText = r;
				},defaultText:InputText);
			}

			public void GetOutputString(object sender, ExecutedRoutedEventArgs e)
			{
				var panel = e.Parameter as Panel;

				Core.ShowTextDialog(r =>
				{
					OutputText = r;
				}, defaultText: OutputText);
			}

			public void SelectSavePath(object sender, ExecutedRoutedEventArgs e)
			{
				Core.SelectPathDialog(r =>
				{
					OutputPath = r;
				}
				,
				initialDirectory:OutputPath
				);
			}

			public void SelectOpenPath(object sender, ExecutedRoutedEventArgs e)
			{
				Core.SelectPathDialog(r =>
				{
					InputPath = r;
				}
				,
				initialDirectory:InputPath
				);
			}

			public void SaveSetting(object sender, ExecutedRoutedEventArgs e)
			{
				SaveSettings();
				SaveTime = DateTime.Now;
			}

			public void ClearOutput(object sender, ExecutedRoutedEventArgs e)
			{
				Items.Clear();
			}

			public void SelectConfig(object sender,ExecutedRoutedEventArgs e)
			{
				var panel = e.Parameter as Panel;

				Core.ShowTextDialog(r =>
				{
					if (String.IsNullOrWhiteSpace(r))
					{
						ConfigSettings.Remove(ConfigTitle);
					}
					else
					{
						TConfig cfg;//= ConfigSettings.GetOrNew(r,ConfigSettings.Default);
						lock (ConfigSettings)
						{
							if (ConfigSettings.Contains(r))
							{
								cfg = ConfigSettings[r];
							}
							else
							{
								cfg = new TConfig()
								{
									ConfigTitle = r
								};
								ConfigTitle = r;
								SaveConfig(cfg);
							}
						}
						ConfigSettings.Default = cfg;
					}
					OnConfigChanged();
				},defaultText: ConfigTitle,otherTexts: ConfigSettings.Keys,messageText:"选择或者输入新的配置名称，\r\n输入空的名称将删除当前配置：");
			}

			protected virtual void OnConfigChanged()
			{
				LoadConfig(ConfigSettings.Default);
			}

			public readonly SubcommandCollection<string> InputStringSubcommands = new SubcommandCollection<string>();
			public readonly SubcommandCollection<string> SelectPathSubcommands = new SubcommandCollection<string>();
			public readonly SubcommandCollection<string> SelectFileSubcommands = new SubcommandCollection<string>();
			public void Subcommands(object sender, ExecutedRoutedEventArgs e)
			{
				var subcommandName = e.Parameter as string;
				if (null==subcommandName)
				{
					MessageBox.Show("子命令不支持键盘快捷键操作！");
				}
				else if (InputStringSubcommands.Contains(subcommandName))
				{
					var p = InputStringSubcommands[subcommandName];
					Core.ShowTextDialog(r =>
					{
						p.Callback(r);
					}, defaultText:(p.GetDefault==null?null: p.GetDefault()), otherTexts: (null==p.GetOthers?null:p.GetOthers()), messageText: p.Message);
				}
				else if (SelectFileSubcommands.Contains(subcommandName))
				{
					var p = SelectFileSubcommands[subcommandName];
					Core.SelectFileDialog(r =>
					{
						p.Callback(r);
					}
					, 
					initial: (null==p.GetDefault?null:p.GetDefault())
					,
					filter: (null == p.GetOthers ? null : p.GetOthers())
					,
					message:p.Message
					);
				}
				else if (SelectPathSubcommands.Contains(subcommandName))
				{
					var p = SelectPathSubcommands[subcommandName];
					Core.SelectPathDialog(r =>
					{
						p.Callback(r);
					}, initialDirectory: (null==p.GetDefault?null:p.GetDefault()));
				}
				else
				{
					MessageBox.Show(String.Format(" “{0}” 功能未实现。", subcommandName));
				}
			}
		}

		[Obsolete(Jiuyong.Consts.Texts.ObsoleteOld+"：“FilesViewModel<TConfig,TItem>”")]
		public abstract class FilesViewModel<TConfig> : FilesViewModel<TConfig, string>
		where TConfig:FilesConfig,new()
		{
		}
	}

	public abstract class FilesConfig
	{
		public string InputText;
		public string InputPath;
		public string OutputText;
		public string OutputPath;

		public string ConfigTitle;

		//public abstract void Save();
		//public FilesConfig()
		//{
		//}

		//public FilesConfig(FilesConfig sourceConfig):this()
		//{
		//}
	}
}
